﻿using System.Collections.Generic;
using System.Windows.Forms;

namespace Borg.Framework
{
    public class FlowLayoutPanel : System.Windows.Forms.FlowLayoutPanel, IAttachable
    {
        public FlowLayoutPanel()
        {
            Enabled = false;
        }

        public void Attach(SlotInfo slot)
        {
            Slot = slot;
            
            Slot.Registered += SlotRegistered;
            Slot.Deregistered += SlotDeregistered;
            
            Controls.Clear();

            foreach (var plugType in Slot.RegisteredPlugTypeInfos)
                SlotRegistered(this, new RegisterEventArgs(Slot, plugType, null));

            Enabled = true;
        }

        public void Detach()
        {
            Enabled = false;

            Slot.Registered -= SlotRegistered;
            Slot.Deregistered -= SlotDeregistered;
            
            Controls.Clear();
            Slot = null;
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);

            if (Slot != null)
                Detach();
        }

        private void SlotDeregistered(object sender, RegisterEventArgs args)
        {
            var key = args.PlugTypeInfo.ToString();

            while (Controls.ContainsKey(key))
            {
                Control control = Controls[key];

                if (control is IAttachable)
                    ((IAttachable) control).Detach();

                Controls.RemoveByKey(key);
            }
        }

        private void SlotRegistered(object sender, RegisterEventArgs args)
        {
            if (Registered == null)
                return;

            foreach (var control in Registered(args))
            {
                control.Name = args.PlugTypeInfo.ToString();

                if (control is IAttachable)
                    ((IAttachable) control).Attach(Slot);

                Controls.Add(control);
            }
        }

        public RegisterCallback Registered { get; set; }

        public SlotInfo Slot { get; private set; }

        public delegate IEnumerable<Control> RegisterCallback(RegisterEventArgs args);
    }
}

